use std::fmt::Arguments;
use std::sync::{Arc, Mutex};

use std::sync::mpsc::{self, Sender};
use std::thread;
use std::time::{Duration, SystemTime};

use crate::ltools::lfile;
use crate::ltools::lring;
use crate::ltools::ltime;
const AES_KEY: &str = "ajdklnlzxdxkyzqp";

/*
 * 日志打印辅助类
*/
#[derive(Debug)]
pub(crate) struct LogInfo {
    // 地址
    addr: String,
    // 内容
    content: String,
}

impl LogInfo {
    fn new(
        addr: String,
        content: String, ) -> Self {
        LogInfo {
            addr,
            content,
        }
    }
}


pub struct LogUtils {
    // 日志大小
    log_size: u64,
    // 日志数量
    log_num: usize,
    // 日志地址
    addr: String,
    //
    sender: Sender<LogInfo>,
}

impl LogUtils {
    /* 构建函数 */
    fn build_self() -> Arc<Mutex<Self>> {
        let (tx, rx) = mpsc::channel::<LogInfo>();
        let runtime = tokio::runtime::Runtime::new().unwrap();
        std::thread::spawn(move || {
            runtime.block_on(async move {
                // tokio::spawn(async move {
                for rx in rx {
                    write_log_async(rx).await;
                }
                // }).await.unwrap();
            });
        });

        Arc::new(Mutex::new(Self {
            log_size: 5 * 1024 * 1024,
            log_num: 9,
            addr: String::from(r"D:\cache\citc\"),
            sender: tx,
        }))
    }

    /* 获取单例 */
    pub fn get_instance() -> Arc<Mutex<Self>> {
        static mut INSTANCE: Option<Arc<Mutex<LogUtils>>> = None;
        unsafe {
            INSTANCE.get_or_insert_with(|| {
                LogUtils::build_self()
            }).clone()
        }
    }

    pub(crate) fn init(&self) {}

    fn send_data(&self, data: LogInfo) {
        self.sender.clone().send(data).unwrap();
    }

    pub fn write_log(&self, level: &str, content: String) {
        let mut lev_color = "";
        if level == "INFO" {
            lev_color = "\x1b[32m"
        } else if level == "ERROR" {
            lev_color = "\x1b[31m"
        } else if level == "WARN" {
            lev_color = "\x1b[33m"
        }

        let adr = self.get_mtc_path();
        let content = format!("{} SDK: {} {}{}: \x1b[0m{}\n",
                              ltime::get_now_format_time(), get_thread_info(), lev_color, level, content);
        // let content = lring::aes_encode_str(AES_KEY,content.as_str());
        self.send_data(LogInfo::new(
            adr,
            content,
        ));
    }

    /////////////////////////////////////

    /* 获取要写入的文件地址 */
    pub(crate) fn get_mtc_path(&self) -> String {
        let list = lfile::read_all_file(self.addr.as_str()).expect("获取地址失败");
        let mut list_mtc: Vec<(String, String)> = list.into_iter().filter(|(adr, name)| {
            name.starts_with("MTC")
        }).collect();

        if let Some((adr, name)) = list_mtc.last() {
            if lfile::file_size(adr) > self.log_size {
                if list_mtc.len() >= self.log_num {
                    lfile::delete(adr);
                }
                format!(r"{}MTC_{}.log", self.addr, ltime::get_print_format_time())
            } else {
                adr.to_string()
            }
        } else {
            format!(r"{}MTC_{}.log", self.addr, ltime::get_print_format_time())
        }
    }
}

/* 异步写入文件 */
async fn write_log_async(data: LogInfo) {
    print!("{}", data.content);
    lfile::write_file(data.addr.as_str(), data.content.as_str(), true).unwrap()
}

/* 获取线程信息 */
fn get_thread_info() -> String {
    let cuth = thread::current();
    let mut cname = "";
    if let Some(t) = cuth.name() { cname = t };
    format!("{:?}({:?})", cname, cuth.id())
}

fn get_log_level(l: LogLevel) -> String {
    match l {
        LogLevel::INOF => { "INFO".to_string() }
        LogLevel::DEBUG => { "DEBUG".to_string() }
        LogLevel::ERROR => { "ERROR".to_string() }
        _ => { "INFO".to_string() }
    }
}

enum LogLevel {
    INOF,
    DEBUG,
    ERROR,
}







































